home *** CD-ROM | disk | FTP | other *** search
- #include <SetupA4.h>
- #include <ExternalInterface.h>
- #include <stdio.h>
- #include <string.h>
-
- #define kMinStackSpace 6000 /* Give up if less than this much stack left */
-
- static ExternalCallbackBlock *cb;
-
- static char buf[256];
- static long lastLine;
- static long blockSize;
- static short doneSoFar;
-
- pascal void main(ExternalCallbackBlock *callbacks, WindowPtr w);
-
-
- /*
- * Recursive routine to insert the size (in blocks) and name of a directory
- * at the current text location. Indentation is determined by the recursion
- * level, "level". Returns a negative number if error (out of stack or
- * user canceled).
- */
- static long InsertFolderSize( short vRefNum, long dirID, Str63 dirName,
- short level )
- {
- long thisSize, increment;
- CInfoPBRec cipbr; /* local pb */
- HFileInfo *fpb = (HFileInfo *)&cipbr;
- DirInfo *dpb = (DirInfo *) &cipbr;
- short idx;
- Str255 filename;
- short err, i;
- long thisLine;
- long selStart, selEnd, firstChar;
- Boolean hasSubDirs = false;
-
- fpb->ioVRefNum = vRefNum;
- fpb->ioNamePtr = filename;
-
- thisSize = 0;
-
- /*
- * Insert directory name at the beginning of current line.
- * (We'll add indentation later.) Then save current line number
- * and insert a carriage return.
- */
- cb->GetSelection( &selStart, &selEnd, &firstChar );
- thisLine = cb->GetLineNumber( selStart );
- sprintf( &buf[0], "%#s\r", dirName );
- cb->Insert( buf, strlen(buf) );
-
- if( (thisLine+1) > lastLine )
- lastLine = thisLine+1;
-
- /*
- * Index through all files and folders in the directory.
- */
- for( idx=1; TRUE; idx++)
- {
- if( 0 == level )
- {
- doneSoFar = idx * 1000;
- }
- if( cb->DoProgress( doneSoFar ) ) /* Allow abort */
- {
- thisSize = -1;
- break;
- }
-
- fpb->ioDirID = dirID; /* must set on each loop */
- fpb->ioFDirIndex = idx;
-
- if( PBGetCatInfo( &cipbr, FALSE ) )
- break; /* exit when no more entries */
-
- if (fpb->ioFlAttrib & 16) /* If it's a folder... */
- {
- /*
- * This entry is a folder. Check stack space, and if that's okay, recurse.
- */
- hasSubDirs = true;
- if( StackSpace() < kMinStackSpace )
- {
- cb->Insert( "Out of memory!\r", 15 );
- thisSize = -1;
- break;
- }
- increment = InsertFolderSize( vRefNum, dpb->ioDrDirID, filename, level+1 );
- if( increment >= 0 )
- {
- thisSize += increment;
- }
- else /* error -- bubble back to top level without doing more work */
- {
- thisSize = increment;
- break;
- }
- }
- else
- {
- /*
- * This entry is a file. Add its resource and data fork physical
- * lengths to the size of the parent folder.
- */
- thisSize += fpb->ioFlPyLen + fpb->ioFlRPyLen;
- }
- }
-
- if( thisSize >= 0 )
- {
- /*
- * Got the size of the parent folder. Insert indentation spaces and
- * the size, in blocks.
- */
- cb->SetSelection( selStart, selStart, -1 );
- for( i=0; i<(level*2); i++ )
- buf[i] = ' ';
-
- sprintf( &buf[i], "%6ld ", thisSize/blockSize );
- cb->Insert( buf, strlen(buf) );
- if( hasSubDirs )
- {
- /*
- * If we had to recurse while doing this directory,
- * we need to set the insertion point at the end of the last
- * line we've written, so the next directory at this level
- * will go there.
- */
- selStart = (cb->GetLineEnd( cb->GetLinePos( lastLine ) ) );
- cb->SetSelection( selStart, selStart, -1 );
- }
- else
- {
- selStart = (cb->GetLineStart( cb->GetLinePos( thisLine + 1) ) );
- cb->SetSelection( selStart, selStart, -1 );
- }
- }
-
- return thisSize;
- }
-
-
- pascal void main(ExternalCallbackBlock *callbacks, WindowPtr w)
- {
- short vRefNum;
- long dirID;
- ParamBlockRec vpb;
- CInfoPBRec cipbr;
- HFileInfo *fpb;
- DirInfo *dpb;
- Str255 filename;
- short i;
- short iErr;
-
- RememberA0();
- SetUpA4();
-
- fpb = (HFileInfo *)&cipbr; /* Don't initialize at declaration */
- dpb = (DirInfo *) &cipbr; /* (or RememberA0 will remember &cipbr!) */
-
- cb = callbacks;
- lastLine = 0;
-
- if( callbacks->version >= 3 )
- {
- if( callbacks->GetFolder( "\pPlease find the starting folder.", &vRefNum, &dirID ) )
- {
- w = callbacks->NewDocument();
- if (w)
- {
- /*
- * Got a folder and new window.
- * Find the volume blocksize.
- */
- vpb.volumeParam.ioVolIndex = 0;
- vpb.volumeParam.ioVRefNum = vRefNum;
- iErr = PBGetVInfo( &vpb, FALSE );
- if( !iErr )
- {
- blockSize = vpb.volumeParam.ioVAlBlkSiz;
-
- /*
- * Get info about top directory, so we can pass its name.
- */
- fpb->ioVRefNum = vRefNum;
- fpb->ioNamePtr = filename;
- fpb->ioDirID = dirID;
- fpb->ioFDirIndex = -1; /* Just get info about the directory */
- iErr = PBGetCatInfo( &cipbr, FALSE );
- }
- if( !iErr )
- {
- /*
- * Here we go. Call the recursive routine.
- */
- cb->StartProgress( "\pdu progress", dpb->ioDrNmFls * 1000L, TRUE );
- doneSoFar = 0;
- InsertFolderSize( vRefNum, dirID, filename, 0 );
- cb->DoneProgress();
- }
- }
- }
- }
-
- RestoreA4();
- }
-
-
-
-
-